using ET;
using FairyGUI;
using System;
using System.Collections.Generic;

namespace Core
{

    public class FGUIComponent : Entity, IAwake
    {
        private readonly Dictionary<string, Type> binders = new Dictionary<string, Type>();
        private readonly Dictionary<Type, IFGUIWindow> windows = new Dictionary<Type, IFGUIWindow>();

        void IAwake.Awake()
        {
            var types = World.GetComponent<CodeTypes>().GetTypes(typeof(BinderAttribute));
            foreach ((string _, Type type) in types)
            {
                object[] attrs = type.GetCustomAttributes(typeof(BinderAttribute), false);
                if (attrs.Length == 0)
                    continue;

                var binderAttribute = attrs[0] as BinderAttribute;
                binders[binderAttribute.PackageName] = type;
            }
        }

        public async ETTask<T> GetWindowAsync<T>(params object[] args) where T : class, IFGUIWindow
        {
            var windowType = typeof(T);
            if (windows.TryGetValue(windowType, out var window))
            {
                return window as T;
            }

            window = Activator.CreateInstance(windowType) as IFGUIWindow;
            if (window == null)
            {
                Log.Error($"create {windowType} fail!");
                return default;
            }

            await window.LoadAsync(packageName =>
            {
                binders.TryGetValue(packageName, out var binder);
                return binder;
            }, args);

            if (!window.isVaild)
            {
                return default;
            }

            windows[windowType] = window;

            World.Main.EventSystem.RegisterSystem(window);

            return window as T;
        }

        public bool HasWindow<T>() where T: IFGUIWindow
        {
            return  windows.ContainsKey(typeof(T));
        }

        public async ETTask<T> ShowWindow<T>() where T : class, IFGUIWindow
        {
            var window = await GetWindowAsync<T>();
            window?.Show();
            return window;
        }

        public void DestroyWindow<T>() where T : IFGUIWindow
        {
            if(windows.TryGetValue(typeof(T), out var window))
            {
                window?.Dispose();
                windows.Remove(typeof(T));
            }
        }

        public void DestroyAllWindow()
        {
            foreach (var window in windows.Values)
            {
                window?.Dispose();
            }
            windows.Clear();
        }

    }
}